package org.activequant.util.ib.marketscanners;

import java.text.SimpleDateFormat;
import java.util.TimeZone;

import org.activequant.core.domainmodel.InstrumentSpecification;
import org.activequant.core.domainmodel.marketscanner.InstrumentSpecificationDetails;
import org.activequant.core.domainmodel.marketscanner.ScanCriteria;
import org.activequant.util.ib.IBTwsConnection;

import com.ib.client.ContractDetails;
import com.ib.client.ScannerSubscription;

public class ScannerUtil {
	
	public static ScannerSubscription convertToScannerSubscription(ScanCriteria criteria){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
		
		com.ib.client.ScannerSubscription subscription = new com.ib.client.ScannerSubscription();
		
		if(criteria.getScanCode()==null)throw new IllegalArgumentException("Missing ScanCode in spec");
		subscription.scanCode(criteria.getScanCode());
		
		subscription.numberOfRows(setInt(criteria.getNumberOfRows()));
		
		subscription.instrument(criteria.getInstrument());
		
		subscription.locationCode(criteria.getLocationCode());
		subscription.abovePrice(setDouble(criteria.getAbovePrice()));
		subscription.belowPrice(setDouble(criteria.getBelowPrice()));
		subscription.aboveVolume(setInt(criteria.getAboveVolume()));
		subscription.averageOptionVolumeAbove(setInt(criteria.getAverageOptionVolumeAbove()));
		subscription.marketCapAbove(setDouble(criteria.getMarketCapAbove()));
		subscription.marketCapBelow(setDouble(criteria.getMarketCapBelow()));
		subscription.moodyRatingAbove(criteria.getMoodyRatingAbove());
		subscription.moodyRatingBelow(criteria.getMoodyRatingBelow());
		subscription.spRatingAbove(criteria.getSpRatingAbove());
		subscription.spRatingBelow(criteria.getSpRatingBelow());
		if (criteria.getMaturityDateAbove() != null) {
			subscription.maturityDateAbove(sdf.format(criteria.getMaturityDateAbove().getTimeStamp().getDate()));
		}
		if (criteria.getMaturityDateBelow() != null) {
			subscription.maturityDateBelow(sdf.format(criteria.getMaturityDateBelow().getTimeStamp().getDate()));
		}
		subscription.couponRateAbove(setDouble(criteria.getCouponRateAbove()));
		subscription.couponRateBelow(setDouble(criteria.getCouponRateBelow()));
		subscription.excludeConvertible(criteria.getExcludeConvertible());
		subscription.scannerSettingPairs(criteria.getScannerSettingPairs());
		subscription.stockTypeFilter(criteria.getStockTypeFilter());
		
		return subscription;
	}
	
	public static InstrumentSpecificationDetails convertToInstrumentSpecificationDetails(ContractDetails details) throws Exception{
		InstrumentSpecification instrumentSpecification=IBTwsConnection.convertToInstrument(details.m_summary);
		InstrumentSpecificationDetails result=new InstrumentSpecificationDetails();
		result.setInstrumentSpecification(instrumentSpecification);
		result.setMarketName(details.m_marketName);
		result.setTradingClass(details.m_tradingClass);
		result.setMinTick(details.m_minTick);
		result.setPriceMagnifier(details.m_priceMagnifier);
		result.setLongName(details.m_longName);
		result.setOrderTypes(details.m_orderTypes);
		result.setValidExchanges(details.m_validExchanges);
		//bond values
		result.setCusip(details.m_cusip);
		result.setRatings(details.m_ratings);
		result.setDescAppend(details.m_descAppend);
		result.setBondType(details.m_bondType);
		result.setCouponType(details.m_couponType);
		result.setCallable(details.m_callable);
		result.setPutable(details.m_putable);
		result.setCoupon(details.m_coupon);
		result.setConvertible(details.m_convertible);
		result.setMaturity(details.m_maturity);
		result.setIssueDate(details.m_issueDate);
		result.setNextOptionDate(details.m_nextOptionDate);
		result.setNextOptionType(details.m_nextOptionType);
		result.setNextOptionPartial(details.m_nextOptionPartial);
		result.setNotes(details.m_notes);
		
		result.setContractMonth(details.m_contractMonth);
		result.setIndustry(details.m_industry);
		result.setCategory(details.m_category);
		result.setSubcategory(details.m_subcategory);
		result.setTimeZoneId(details.m_timeZoneId);
		result.setTradingHours(details.m_tradingHours);
		result.setLiquidHours(details.m_liquidHours);
		return result;
	}
	
	private static int setInt(int value) {
        if(value==ScanCriteria.NOT_SET){
        	return Integer.MAX_VALUE;
        }else{
        	return value;
        }
    }
	
	private static double setDouble(double value) {
        if(value==ScanCriteria.NOT_SET){
        	return Double.MAX_VALUE;
        }else{
        	return value;
        }
    }
}
